# -*- coding: utf-8 -*-
"""
"""

from datetime import datetime

from sqlalchemy import *
from sqlalchemy.orm import mapper, relation
from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import Integer, Unicode

from abserver.model import DeclarativeBase, metadata, DBSession





class Build(DeclarativeBase):
    """The Build entity describes a single build that has been set off on an autobuild
    environment. One gets created when the abserver idl interface "register_build" is called.
    """
    # table options
    __tablename__ = 'build'

    # columns
    build_id = Column(Integer, primary_key=True, autoincrement=True)
    sccs_time = Column(DateTime, nullable=False)
    build_started = Column(DateTime, nullable=False)
    build_finished = Column(DateTime, nullable=True)
    building = Column(Boolean)
    builder_id = Column(Integer, ForeignKey('builder.builder_id'), nullable=False)
    component_id = Column(Integer, ForeignKey('component.component_id'), nullable=True) # the component is only known after construction
    branch_id = Column(Integer, ForeignKey('branch.branch_id'), nullable=True) # the branch is only known after construction

    # relationships
    builder = relation('Builder', backref='builds')
    component = relation('Component', backref='builds')
    ## tasks
    branch = relation('Branch', backref='builds')

    def __init__(self, builder, timestamp):
        self.builder = builder
        self.sccs_time = datetime.utcfromtimestamp(timestamp)
        self.build_started = datetime.utcnow()
        self.building = True
        DBSession.add(self)

    @classmethod
    def select_by_view(cls, view):
        q = DBSession.query(cls)
        if not view:
            return q # This could be a huge list!
        if view.buildview_component is not None:
            q = q.filter(or_ (Build.component == None, Build.component == view.buildview_component))
        if view.buildview_branch is not None:
            q = q.filter(or_(Build.branch == None,    Build.branch == view.buildview_branch))
        if view.buildview_start_time is not None:
            q = q.filter(or_(Build.sccs_time == None, Build.sccs_time > view.buildview_start_time))
        if view.buildview_end_time is not None:
            q = q.filter(or_(Build.sccs_time == None, Build.sccs_time < view.buildview_end_time))
        if view.buildblessings:
            q = q.join(Build.tasks).join(Task.blessing).filter(BuildBlessing.blessing_level.in_([bless_obj.blessing_level for bless_obj in view.buildblessings]))
        return q

    @classmethod
    def get(cls, build_id):
        return DBSession.query(cls).filter(cls.build_id == build_id).first()

    @classmethod
    def select_by_time(cls, oldest):
        return DBSession.query(cls).filter( or_( cls.build_started>=oldest,
                                                 cls.build_finished is None,
                                                 cls.build_finished>oldest
                                                 )).all()

    # Determine whether a build/test passed or failed based from varieties built
    def build_status_by_task(self):
        for task in self.tasks:
            if task.build_status == 4 or task.build_status == 5:
               return task.build_status
        return -1

    
    def most_severe_status(self):
        from abserver.model import Task
        status = -1
        severity = -1
        for task in self.tasks:
            st = task.build_status
            sv = Task.STATUS_SEVERITY[st]
            if sv > severity:
                severity = sv
                status = st
        return status
            
        
    def component_name(self):
        c = self.component
        if not c:
            return ""
        return c.component_name

    def branch_name(self):
        b = self.branch
        if not b:
            return ""
        return b.branch_name

